


#include "fun.h"


static int i=0,j=0;
static int file_m_id=0,file_c_id=0;


/*Called by pcap_loop dumps packets to stdout */

void
net_callb_r_d (u_char *args,
			   const struct pcap_pkthdr *header,
			   const u_char *pkt_data){

  int in_p=0,b=0;
  struct ether_header *ether_h; /*pointer to ethernet_header structure */
  
  /*I post here packet length ant time when it was received */  
  printf("\n\nEthernet Frame %d:\n is length: %d bytes\n",i++,header->len);
  printf(" was recieved at: %s\n",ctime((const time_t*)&header->ts.tv_sec));

  /*I go through the packet and list all bytes in hex */
  for (in_p=0,b=1;in_p<header->len;in_p++,b++)
	if(b<12){
		print_h(pkt_data[in_p]);
	}	

	else{
	  print_h(pkt_data[in_p]);
	  printf("\n");
	  b=0;
	}

  /*make from my generic data ethernet frame ;)*/
  ether_h=(struct ether_header *)pkt_data;

#ifdef DEBUG
  printf("\n!!%x ",ntohs(ether_h->ether_type));
#endif
  /*I have bytes in big endianess network number */
  if (ntohs(ether_h->ether_type)>0x05dc)
	printf("\nFrame is EthernetII type.\n\n");
  else
	printf("\nFrame is 802.3 type.\n\n");
  
}

void
net_callb_r_a (u_char *args,
			   const struct pcap_pkthdr *header,
			   const u_char *pkt_data){

  struct ether_header *ether_h; /*pointer to ethernet_header structure */  
  struct llc          *llc_h;   /*pointer to llc_header structure*/

  /*first I prit raw frame to screen*/
  net_callb_r_d(args,header,pkt_data);

  /*typecast data to ethernet frame header */
  ether_h=(struct ether_header *)pkt_data;

  /*print mac addresses */
  printf("Destination MAC address is: %s\n", ether_ntoa((struct ether_addr *)ether_h->ether_dhost));

  printf("Source MAC address is: %s\n", ether_ntoa((struct ether_addr *)ether_h->ether_shost));

  /*all in frame is bgi endian */
  /*ethernet II frame */
  if (ntohs(ether_h->ether_type)>0x05dc){
	/*convert ether_type to name of protocol*/
	ep_num_n(ether_h->ether_type);
	
	if((ntohs(ether_h->ether_type))==ETHERTYPE_IP)
	  /*pritns aditional data about TCP/IP*/
	  ch_tcp_ip(pkt_data,0);
	else
	  /*details about other protocols I don;t print */
	  return;
  }
  else{
	/*802.3frame */
	llc_h=(struct llc*)(pkt_data+sizeof(struct ether_header));

	printf("\nDSAP address: %x\n",llc_h->llc_dsap);
	printf("SSAP address: %x\n",llc_h->llc_ssap);

	/*translate dsap to name of upper protocol */
	switch(llc_h->llc_dsap){
	case 0xff:
	  printf("\nUpper level protocol is RAW IPX\n");
	  break;
	case 0xe0:
	  printf("\nUpper level protocol is Novell/Netware IPX\n");
	  break;
	case 0x00:
	  printf("\nUpper level protocol is NULL SAP packet\n");
	  break;
	case 0x06:
	  printf("\nUpper level protocol is IP\n");
	  ch_tcp_ip(pkt_data,sizeof(struct llc));
	  break;
	case 0x0e:
	  printf("\nUpper level protocol is PROWAY\n");
	  break;
	case 0x42:
	  printf("\nUpper level protocol is BPDU\\spanning tree \n");
	  break;
	case 0xAA:
	  printf("\nUpper level protocol is SNAP\n");
	  /*translate ether_type number to protocol name */
	  ep_num_n(llc_h->llc_un.type_snap.ether_type);
	  /*Sanp header tells me thatI have here IP so I check how my IP looks like */
	  if((ntohs(llc_h->llc_un.type_snap.ether_type))==ETHERTYPE_IP)
		ch_tcp_ip(pkt_data,sizeof(struct llc));
	  else
		return;
	  break;
	  
	case 0xf4:
	  printf("\nUpper level protocol is Lan management \n");
	  break;
	case 0xfe:
	  printf("\nUpper level protocol is ISO Network Layer Protocols\n");
	  break;
	}
	
  }
  return;
}

/*this function reads ether_header and try to assign tcp_header and if its finds
 *TCP syn segment store it in fr_list
 */
void
net_callb_r_c (u_char *args,
			   const struct pcap_pkthdr *header,
			   const u_char *pkt_data){

  struct ether_header *ether_h; /*pointer to ethernet_header structure */  
  struct llc          *llc_h;  /*pointer to llc_header structure*/
  struct tcphdr       *tcp_h;  /*pointer to tcp header structure*/

  
  ether_h=(struct ether_header *)pkt_data;

  if(!s_m_list_addr(ether_h->ether_dhost,ether_h->ether_shost)){
  	ins_m(ether_h);
  }
  
  /*all in frame is big endian */
  /*ethernet II frame */

  if (ntohs(ether_h->ether_type)>0x05dc){
	/*If this pkt_data contains TCP segment with SYN flag enabled I add it to my list*/
	if (1==get_tcp_syn(pkt_data,sizeof(struct ether_header))){
	  tcp_h=(struct tcphdr*)(pkt_data+sizeof(struct ip)+sizeof(struct ether_header));
	  ins_fr(tcp_h->th_sport,tcp_h->th_dport,ether_h);
	}
  }
  else
	/*802.3 frame */
    {
	  llc_h=(struct llc*)(pkt_data+sizeof(struct ether_header));
	/*If this pkt_data contains TCP segment with SYN flag enabled I add it to my list*/
	  if (llc_h->llc_dsap==0x06)
		if (1==get_tcp_syn(pkt_data,sizeof(struct ether_header)+sizeof(struct llc))){
		  tcp_h=(struct tcphdr*)(pkt_data+sizeof(struct ip)
								 +sizeof(struct ether_header)
								 +sizeof(struct llc));
			ins_fr(tcp_h->th_sport,tcp_h->th_dport,ether_h);
			/*
			  In DSAP header can be IP protocol packet included so I chceks this option
			 */
		}
	/*If this pkt_data contains TCP segment with SYN flag enabled I add it to my list*/
	  if (llc_h->llc_dsap==0xAA)
		if((llc_h->llc_un.type_snap.ether_type)==ETHERTYPE_IP)
		  if(1==get_tcp_syn(pkt_data,sizeof(struct ether_header)+sizeof(struct llc))){
			tcp_h=(struct tcphdr*)(pkt_data+sizeof(struct ip)
								   +sizeof(struct ether_header)
								   +sizeof(struct llc));
			ins_fr(tcp_h->th_sport,tcp_h->th_dport,ether_h);
			/*
			  In DSNAP header can be IP protocol packet included so this checks this option 
   			 */
		  }
	  }

}

void
net_callb_s_con (u_char *args,
				 const struct pcap_pkthdr *header,
				 const u_char *pkt_data){
  
  struct ether_header *ether_h; /*pointer to ethernet_header structure */
  struct ip       *ip_h;       /*pointer to ip header structure*/
  struct tcphdr   *tcp_h;     /*pointer to tcp header structure*/
  struct fr_list *tmp;
  int offset;
  
  /*restore my argument from *args*/
  tmp=(struct fr_list*)args;
  /*I need mac addresses in acctual frame */
  ether_h=(struct ether_header*)(pkt_data);

  file_c_id++;
  /*
	This if test all possible connection options
	A can send or receive frames so A MAC can be included as dhost or shost
	B can send or receive frames so B MAC can be included as dhost or shost
	
  */
  offset=get_offset(pkt_data);
  if((!bcmp(tmp->ether_dhost,ether_h->ether_dhost,6)&&
	  !bcmp(tmp->ether_shost,ether_h->ether_shost,6))||
	 (!bcmp(tmp->ether_dhost,ether_h->ether_shost,6)&&
	  !bcmp(tmp->ether_shost,ether_h->ether_dhost,6))){


	  /*typecast my data to ip packet*/
	  ip_h=(struct ip *)(pkt_data+sizeof(struct ether_header)+offset);

	  if(ip_h->ip_p==6){
		/*typecast my data to tcp header */
		tcp_h=( struct tcphdr*)(pkt_data+sizeof(struct ether_header)+sizeof(struct ip)+offset);

		/*
		  test frame with good MAC to tcp ports numbers 
		 */
		if((tcp_h->th_dport==tmp->th_dport &&
			tcp_h->th_sport==tmp->th_sport)||
		   (tcp_h->th_dport==tmp->th_sport &&
			tcp_h->th_sport==tmp->th_dport)){

		  printf("\n\nID of frame in file is  %d",file_c_id);

		  /*print info about packet */
		  net_callb_r_a(args,header,pkt_data);
		  printf("\nThis frame belongs to selected connection and has id %d\n",j++);
		  
		  if(tcp_h->th_flags==TH_SYN)
			printf("This segment starts connection with TCP SYN flag set to 1\n");

		  if(tcp_h->th_flags==TH_FIN)
			printf("This segment ends connection with TCP FIN flag set to 1\n");

		  if(tcp_h->th_flags==TH_ACK)
			printf("This segment has TCP ACK flag set to 1\n");

		  if(tcp_h->th_flags==TH_RST)
			printf("This segment has TCP RST flag set to 1\n");
		  
		  if(tcp_h->th_flags==TH_PUSH)
			printf("This segment has TCP PUSH flag set to 1\n");
		  
		  if(tcp_h->th_flags==TH_URG)
			printf("This segment has TCP URG flag set to 1\n");
		}
		
		return;

	  }  
	  
  }
}

void
net_callb_s_m (u_char *args,
				 const struct pcap_pkthdr *header,
				 const u_char *pkt_data){
  
  struct ether_header *ether_h; /*pointer to ethernet_header structure */
  struct m_list *tmp;

  
  /*restore my argument from *args*/
  tmp=(struct m_list*)args;
  /*I need mac addresses in acctual frame */
  ether_h=(struct ether_header*)(pkt_data);

  file_m_id++;
  /*
	This if test all possible connection options
	A can send or receive frames so A MAC can be included as dhost or shost
	B can send or receive frames so B MAC can be included as dhost or shost
	
  */
  if((!bcmp(tmp->ether_dhost,ether_h->ether_dhost,6)&&
	  !bcmp(tmp->ether_shost,ether_h->ether_shost,6))||
	 (!bcmp(tmp->ether_dhost,ether_h->ether_shost,6)&&
	  !bcmp(tmp->ether_shost,ether_h->ether_dhost,6))){

	printf("\n\nID of frame in file is  %d",file_m_id);
    net_callb_r_a(args,header,pkt_data);

  }
}

int
ch_tcp_ip (const u_char *pkt_data,int offset){

  char *proto=NULL; 
  struct udphdr   *udp_h;
  struct tcphdr   *tcp_h;
  struct ip       *ip_h;    /*pointer to ip header structure*/
  struct servent  *serv;    /*structure used to resolve port number to aplication protocol*/
  struct protoent *proto_s; /*structure used to resolve ip packet protocol number to name*/

  
  /*typecast my data to ip packet*/
  ip_h=(struct ip *)(pkt_data+sizeof(struct ether_header)+offset);
  printf("\nIP Header length is %x ",ip_h->ip_hl);

  /*printf dest and source ipaddresses from struct ip*/
  printf("\nSource ip address is: %s\n",inet_ntoa(ip_h->ip_src));
  printf("Destination ip address is: %s\n\n",inet_ntoa(ip_h->ip_dst));
  
  /*resolve protocol name  by its number */
  if(!(proto_s=(getprotobynumber(ip_h->ip_p))))
	printf("Protocol above IP has number %d \n",ip_h->ip_p);
  else
	printf("Protocol above IP has name %s\n",proto_s->p_name);

  switch(ip_h->ip_p){

  case 6:
	{
	  /*typecast my data to tcp header */
	  tcp_h=( struct tcphdr*)(pkt_data+sizeof(struct ether_header)+sizeof(struct ip)+offset);
	  
	  /*use function getservbyport to get serv name :)*/
	  /*prints name of protocol which belongs to destination port*/
	  if(!(serv=getservbyport(tcp_h->th_dport,proto)))
		printf("Destination Port number %d is not assigned to  specific aplication(protocol)\n",
			   ntohs(tcp_h->th_dport));
	  else
		printf("Destination Port number %d has assigned aplication %s \n",
			   ntohs(tcp_h->th_dport),serv->s_name);
	  
	  /*prints name of protocol which belongs to source port*/
	  if(!(serv=getservbyport(tcp_h->th_sport,proto)))
		printf("Source Port number %d is not assigned to  specific aplication(protocol)\n",
			   ntohs(tcp_h->th_sport));
	  else
		printf("Source Port number %d has assigned aplication %s \n",
			   ntohs(tcp_h->th_sport),serv->s_name);
#ifdef DEBUG

  	  if(tcp_h->th_flags==TH_SYN)
			  printf("This TCP segment has SYN flag enabled\n");
#endif
	  return 0;
	  break;
	}
  case 17:
	{
	  /*typecast my data to tcp header */
	  udp_h=( struct udphdr*)(pkt_data+sizeof(struct ether_header)+sizeof(struct ip)+offset);
	  
	  /*use function getservbyport to get serv name :)*/
	  if(!(serv=getservbyport(udp_h->uh_dport,proto)))
		printf("Destination Port number %d is not assigned to  specific aplication(protocol)\n",
			   ntohs(udp_h->uh_dport));
	  else
		printf("Destination Port number %d has assigned aplication %s \n",
			   ntohs(udp_h->uh_dport),serv->s_name);
	
	  printf("Source Port has number %d\n", ntohs(udp_h->uh_sport));
	  return 0;
	  break;
	}
  }

  return 1;
}

int
ep_num_n (u_int16_t ether_type){

	switch (ntohs(ether_type)){
	case ETHERTYPE_ARP:
	  printf("\nUpper level protocol type: ARP\n");
	  return 0;
	  break;
	case ETHERTYPE_IP:
	  printf("\nUpper level protocol type: IP\n");
	  return 0;
	  break;
	case  ETHERTYPE_RAWFR:
	  printf("\nUpper level protocol type: RAWFR\n");
	  return 0;
	  break;	
	case ETHERTYPE_REVARP:
	  printf("\nUpper level protocol type: REVARP\n");
	  return 0;
	  break;
	case  ETHERTYPE_IPXNEW:
	  printf("\nUpper level protocol type: IPX\n");
	  return 0;
	  break;
	case  ETHERTYPE_PUP:
	  printf("\nUpper level protocol type: PUP\n");
	  return 0;
	  break;
	case  ETHERTYPE_IEEEPUPAT:
	  printf("\nUpper level protocol type: PUPAT\n");
	  return 0;
	  break;
	case  ETHERTYPE_IEEEPUP:
	  printf("\nUpper level protocol type: PUP\n");
	  return 0;
	  break;
	case  ETHERTYPE_X25:
	  printf("\nUpper level protocol type: X25\n");
	  return 0;
	  break;
	case  ETHERTYPE_VLAN:
	  printf("\nUpper level protocol type: IEEE 802.1Q VLAN\n");
	  return 0;
	  break;
	case  ETHERTYPE_WCCP:
	  printf("\nUpper level protocol type: WCCP\n");
	  return 0;
	  break;

	default:
	  printf("\nUpper level protocol type: %x\n",ntohs(ether_type));
      return 0;
	  break;
	}
	return 1;


}

int
get_tcp_syn (const u_char *pkt_data,int offset){

  struct ip *ip_h;
  struct tcphdr *tcp_h;

  ip_h=(struct ip*)(pkt_data+offset);

  /*I hav tcp packet here;) */
  if(ip_h->ip_p==0x06){
	tcp_h=(struct tcphdr*)(pkt_data+sizeof(struct ip)+offset);

	if(tcp_h->th_flags==TH_SYN)
	  return 1;
	if(tcp_h->th_flags==TH_FIN)
	  return 2;
  }
  return 0;
}

int
get_offset(const u_char *pkt_data){
  struct ether_header *ether_h; /*pointer to ethernet_header structure */  

  /*I need mac addresses in acctual frame */
  ether_h=(struct ether_header*)(pkt_data);
  
  /*I have Ethernet II frame */
  if((ntohs(ether_h->ether_type))==ETHERTYPE_IP)
	return 0;
  else
	return sizeof(struct llc);
}
